#pragma once

#include "../http/HttpContext.h"
#include "Buffer.h"
#include "Callbacks.h"
#include "InetAddress.h"
#include "Logger.h"

#include <atomic>
#include <memory>
#include <string>

class Socket;
class Channel;
class EventLoop;

// TcpServer -> Acceptor -> NewConnection(connfd) -> TcpConnection -> Channel -> Epoller
class TcpConnection : public std::enable_shared_from_this<TcpConnection> {
private:
    void SetState(int state);

    void HandleRead();

    void HandleWrite();

    void HandleClose();

    void HandleError();

public:
    void Send(const std::string& buf);

    /**
     * 发送数据 应用写的快 而内核发送数据慢 需要把待发送数据写入缓冲区，而且设置了水位回调
     **/
    void SendInLoop(const char* data, size_t len);

    void ConnectEstablished();

    void ConnectDestroyed();

    void SetCloseCallback(const CloseCallback& cb) { close_callback_ = cb; }

public:
    TcpConnection(EventLoop* loop, std::string name, int connfd, InetAddress local_addr, InetAddress peer_addr);

    void SetConnectionCallback(const ConnectionCallback& cb);
    void SetMessageCallback(const MessageCallback& cb);
    void SetWriteCompleteCallback(const WriteCompleteCallback& cb);

    void Shutdown();

    void ShutdownInLoop();

    std::string Name();

    EventLoop* Loop();

    void SetHttpContext(const HttpContext& context);

    HttpContext* GetHttpContext();

    ~TcpConnection();

private:
    enum ConnState { Connecting = 1, Connected, DisConnecting, DisConnected };
    EventLoop* loop_;
    std::string name_;
    std::unique_ptr<Socket> socket_;
    std::unique_ptr<Channel> channel_;

    InetAddress local_addr_;
    InetAddress peer_addr_;
    std::atomic_int state_;

    Buffer in_buffer_;   // read
    Buffer out_buffer_;  // write

    HttpContext http_context_;

    ConnectionCallback connection_callback_;  // 有新连接时的回调
    MessageCallback message_callback_;        // 有读写事件发生时的回调
    size_t high_water_mark_;
    HighWaterMarkCallback high_water_mark_callback_;  // 高水位回调：达到预设的"高水位线"阈值时，自动触发，防止系统过载
    CloseCallback close_callback_;

    WriteCompleteCallback write_complete_callback_;  // 消息发送完成后的回调
};